#include "stm32f10x.h"
#include "stm32f10x_dma.h"  
#include "stdint.h"         
#include "MyDMA.h"          


#define UART_RX_BUF_LEN 32  // 缓存总长度固定为32字节
uint8_t UART_RxBuf[UART_RX_BUF_LEN] = {0}; // 内部接收缓存

uint16_t MyDMA_Size;
static DMA_InitTypeDef DMA_InitStruct_RX; 
static DMA_InitTypeDef DMA_InitStruct_TX;

//通用函数
void MyDMA_Init(uint32_t addrA, uint32_t addrB, uint16_t Size)
{
    MyDMA_Size = Size;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_PeripheralBaseAddr = addrA;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
    DMA_InitStructure.DMA_MemoryBaseAddr = addrB;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = Size;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);
    
    DMA_Cmd(DMA1_Channel1, DISABLE);
}

//依旧通用
void MyDMA_Transfer(void)
{
    DMA_Cmd(DMA1_Channel1, DISABLE);
    DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);
    DMA_Cmd(DMA1_Channel1, ENABLE);
    
    while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
    DMA_ClearFlag(DMA1_FLAG_TC1);
}

void MyDMA_UART1_Init(void)
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    
 
    // 串口接收时，串口外设USART1->DR 搬到 内存缓存UART_RxBuf
    DMA_InitStruct_RX.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; // /串口接收数据寄存器地址
    DMA_InitStruct_RX.DMA_MemoryBaseAddr = (uint32_t)UART_RxBuf; //  
    DMA_InitStruct_RX.DMA_DIR = DMA_DIR_PeripheralSRC; // 传输方向
    DMA_InitStruct_RX.DMA_BufferSize = UART_RX_BUF_LEN; // 接收缓存总长度：32字节
    DMA_InitStruct_RX.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    DMA_InitStruct_RX.DMA_MemoryInc = DMA_MemoryInc_Enable; 
    DMA_InitStruct_RX.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStruct_RX.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 
    DMA_InitStruct_RX.DMA_Mode = DMA_Mode_Circular; // 循环模式
    DMA_InitStruct_RX.DMA_M2M = DMA_M2M_Disable; // 不用M2M
    DMA_InitStruct_RX.DMA_Priority = DMA_Priority_Medium; // 中等优先级
    
    DMA_Init(DMA1_Channel5, &DMA_InitStruct_RX); 
    DMA_Cmd(DMA1_Channel5, ENABLE); 
    
   
    // 串口发送时，跟上面方向反过来
    DMA_InitStruct_TX.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; // 目标地址：串口发送数据寄存器（数据到这里发）
    DMA_InitStruct_TX.DMA_MemoryBaseAddr = 0; 
    DMA_InitStruct_TX.DMA_DIR = DMA_DIR_PeripheralDST; // 传输方向：从缓存（存储器）到串口（外设）
    DMA_InitStruct_TX.DMA_BufferSize = 0; // 发送长度
    DMA_InitStruct_TX.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 目标地址不自增：USART1->DR是固定寄存器
    DMA_InitStruct_TX.DMA_MemoryInc = DMA_MemoryInc_Enable; // 源地址自增：发送1字节后，缓存地址+1，取下一个字节
    DMA_InitStruct_TX.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; 
    DMA_InitStruct_TX.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; 
    DMA_InitStruct_TX.DMA_Mode = DMA_Mode_Normal; // 普通模式：发送完成后DMA停止，需手动重启
    DMA_InitStruct_TX.DMA_M2M = DMA_M2M_Disable; 
    DMA_InitStruct_TX.DMA_Priority = DMA_Priority_Medium; // 中等优先级
    
    DMA_Init(DMA1_Channel4, &DMA_InitStruct_TX); // 配置DMA1的Channel4（USART1_TX默认对应Channel4，STM32硬件映射）
    // 注意：发送DMA初始不启用（后续调用MyDMA_UART1_Send时再启用）
    
 
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); // 允许串口接收数据时，触发DMA接收请求
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); // 允许串口发送数据时，触发DMA发送请求
}

void MyDMA_UART1_Send(uint8_t *pData, uint16_t Len)
{
    DMA_Cmd(DMA1_Channel4, DISABLE);
    DMA1_Channel4->CMAR = (uint32_t)pData; // 直接操作寄存器，替代DMA_SetMemoryBaseAddr
    DMA_SetCurrDataCounter(DMA1_Channel4, Len);
    DMA_Cmd(DMA1_Channel4, ENABLE);
}

//给Serial。c的
uint8_t* MyDMA_UART1_GetRxBuf(void)
{
    return UART_RxBuf;
}

//总长
uint16_t MyDMA_UART1_GetRxBufLen(void)
{
    return UART_RX_BUF_LEN;
}

//剩余长度
uint16_t MyDMA_UART1_GetRxRemain(void)
{
    return DMA_GetCurrDataCounter(DMA1_Channel5);
}


void MyDMA_UART1_RestartRx(void)
{
    DMA_Cmd(DMA1_Channel5, DISABLE);
    DMA_SetCurrDataCounter(DMA1_Channel5, UART_RX_BUF_LEN);
    DMA_Cmd(DMA1_Channel5, ENABLE);
}
